

#include "hardware.h"
#include "sys.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "debug.h"
#include "USART.h"
#include "cmd.h"
/* #include "Receivers.h" */
#include "modem.h"
#include "macros.h"
#include "fout.h"
//#include "AuxPort.h"

cmd_msg_t u0_cmd = {0,""};
unsigned char u0_pcmd = 0;

#define   U0_CHAR_ECHO(ch)	while (!(U0LSR & 0x20)); U0THR = ch


//void u0_receiver ( void ) __attribute__ ((interrupt("IRQ")));
void u0_receiver ( void ) __attribute__((noinline));
void u0_ISR_Wrapper( void ) __attribute__((naked));

void u0_receiver ( void )
{
	unsigned char id;
	portBASE_TYPE xHigherPriorityTaskWoken;
	
	while ( ((id = U0IIR) & 0x01) == 0 )
	{
		if ( (id & 0x0E) == 0x04 )
		{
			u0_cmd.cmd_str[u0_pcmd] = U0RBR;

			if ( u0_cmd.cmd_str[u0_pcmd] == '\r' )  
			{
				u0_cmd.cmd_str[u0_pcmd] = 0;
				u0_pcmd = 0;

				xQueueSendFromISR(cmd_queue, &u0_cmd, &xHigherPriorityTaskWoken);
				
				if ( xHigherPriorityTaskWoken == pdTRUE )
				{
					//portYIELD();
					portYIELD_FROM_ISR();
				}
			}
			else
			{
				U0_CHAR_ECHO(u0_cmd.cmd_str[u0_pcmd]);

				u0_pcmd++;
				u0_pcmd %= CMD_IN_BUFFER_SIZE-1;
			}

		}
		else
		{
			U0LSR;
			U0RBR;
		}
	}

	VICVectAddr = 0;             // clear this interrupt from the VIC
}


void u0_ISR_Wrapper( void )
{
	/* Save the context of the interrupted task. */
    portSAVE_CONTEXT();

    /* Call the handler.  This must be a separate function unless you can
    guarantee that no stack will be used. */
    __asm volatile ( "bl u0_receiver" );
    
    /* Restore the context of whichever task is going to run next. */
    portRESTORE_CONTEXT();
}

/* --------------------------------- MODEM --------------------------------- */
/* --------------------------------- MODEM --------------------------------- */
/* --------------------------------- MODEM --------------------------------- */
/* --------------------------------- MODEM --------------------------------- */

void u2_receiver ( void ) __attribute__((noinline));
void u2_ISR_Wrapper( void ) __attribute__((naked));

char u2_rec_buf[U2_REC_BUF_SIZE];
unsigned char pu2_rec_buf = 0;

void u2_receiver ( void )
{
	unsigned char id;
	portBASE_TYPE xHigherPriorityTaskWoken;

	while ( ((id = U2IIR) & 0x01) == 0 )
	{
		if ( (id & 0x0E) == 0x04 )
		{
			u2_rec_buf[pu2_rec_buf] = U2RBR;
			
//			PUTCHAR(u2_rec_buf[pu2_rec_buf]);

			if ( u2_rec_buf[pu2_rec_buf] == 0 )
			{
				pu2_rec_buf = 0;
			}
			else
				// monitor for "<CR><LF>"
				if ( pu2_rec_buf >= 2 && u2_rec_buf[pu2_rec_buf] == '\n'  && u2_rec_buf[pu2_rec_buf-1] == '\r')// && 
				{
					u2_rec_buf[pu2_rec_buf+1] = 0;	/* end of string */
					pu2_rec_buf = 0;
					/* Stop receive */
					//PIN_MODEM_RTS = 0;

					xQueueSendFromISR(modem_out_queue, &u2_rec_buf[0], &xHigherPriorityTaskWoken);
				
					if ( xHigherPriorityTaskWoken == pdTRUE )
					{
						portYIELD_FROM_ISR();
					}

				}
				else
					if ( ++pu2_rec_buf >= U2_REC_BUF_SIZE )
					{
						pu2_rec_buf = 0;
					}
			
		}
		else
		{
			U2LSR;
			U2RBR;
		}
	}
	
	VICVectAddr = 0;             // clear this interrupt from the VIC
}

void u2_ISR_Wrapper( void )
{
	/* Save the context of the interrupted task. */
    portSAVE_CONTEXT();

    /* Call the handler.  This must be a separate function unless you can
    guarantee that no stack will be used. */
    __asm volatile ( "bl u2_receiver" );
    
    /* Restore the context of whichever task is going to run next. */
    portRESTORE_CONTEXT();
}


#define   FDIV		((unsigned short)((PCLK/(16.0*br))+0.5))

void UART0_Init ( unsigned long br ) 
{

	PINSEL0 |= 0x00000050; // Select UART0 TXD/RXD

	U0IER = 0x00;                         // disable all interrupts
	U0IIR;                                // clear interrupt ID
	U0RBR;                                // clear receive register
	U0LSR;                                // clear line status register

	U0FCR = 7; // Enable and clear FIFO's ; trigger level(bit7,6) == 0 -> trigger on each byte 
	U0LCR = 0x83; // 8N1, enable Divisor latch bit
	
	U0DLL = FDIV;
	U0DLM = FDIV >> 8;

	U0LCR = 3; // Disable Divisor latch bit

	// ISR

	VICIntSelect    &= ~(1UL<<6);
	VICVectAddr6     = (unsigned int)u0_ISR_Wrapper;
	//VICVectAddr6     = (unsigned int)u0_receiver;
	VICIntEnClr      = (1UL<<6);
	VICVectPriority6 = 10;
	VICIntEnable     = (1UL<<6);

	U0IER = UIER_RBR;

}

void UART2_Init ( unsigned long br )
{
	PINSEL0 |= (unsigned long)(1UL<<20); // Select UART2 TXD
	PINSEL0 |= (unsigned long)(1UL<<22); // Select UART2 RXD

	PCONP |= (1UL<<24); 			  /* UART2 */
	
	U2IER = 0x00;                         // disable all interrupts
	U2IIR;                                // clear interrupt ID
	U2RBR;                                // clear receive register
	U2LSR;                                // clear line status register

	U2FCR = 7; // Enable and clear FIFO's
	U2LCR = 0x83; // 8N1, enable Divisor latch bit

	U2DLL = FDIV;
	U2DLM = FDIV >> 8;


	U2LCR = 3; // Disable Divisor latch bit

	VICIntSelect    	&= ~(1UL<<28);
	VICVectAddr28     = (unsigned int)u2_ISR_Wrapper;
	VICIntEnClr      	= (1UL<<28);
	VICVectPriority28 = 12;
	VICIntEnable     	= (1UL<<28);
	
	U2IER = UIER_RBR;
}


void UART3_Init ( unsigned long br )
{
	PINSEL1 |= (unsigned long)(3UL<<18); // Select UART3 TXD
	PINSEL1 |= (unsigned long)(3UL<<20); // Select UART3 RXD

	PCONP |= (1UL<<25); 			  /* UART3 */
	
	U3IER = 0x00;                         // disable all interrupts
	U3IIR;                                // clear interrupt ID
	U3RBR;                                // clear receive register
	U3LSR;                                // clear line status register

	U3FCR = 7; // Enable and clear FIFO's
	U3LCR = 0x83; // 8N1, enable Divisor latch bit

	/* U3DLL = (unsigned char)((PCLK/(br * 16))); // baud rate fixed to 19200 @ PCLK = 12 Mhz */
	/* U3DLM = (unsigned char)(((PCLK/(br * 16)))>>8 );  // baud; */

	U3DLM = (unsigned char)FDIV/256;
	U3DLL = (unsigned char)FDIV%256;


	U3LCR = 3; // Disable Divisor latch bit

/* 	VICIntSelect    	&= ~(1UL<<28); */
/* 	VICVectAddr28     = (unsigned int)Modem_RXD; */
/* 	VICIntEnClr      	= (1UL<<28); */
/* 	VICVectPriority28 = 13; */
/* 	VICIntEnable     	= (1UL<<28); */
	
/* 	U3IER = UIER_RBR; */
}


void uarts_init ( void )
{	
//	Init_ModemReceiver();
	UART0_Init(115200);
	
	
	UART2_Init(115200);
	//UART3_Init(9600);
	
	PIN_MODEM_RTS_DIR = PIN_OUTPUT;
	PIN_MODEM_RTS = 0;
	PIN_MODEM_CTS_DIR = PIN_INPUT;
	
}

/* ------------------------------------------------------- */

#if 1

void putch ( unsigned char ch, int port )
{
//	unsigned long CTS_TimeOut = 80000000; /* ~16 Sec */

	if ( port == FOUT_DEV_U2 )
	{

#ifdef   FLOW_CONTROL		
		while ( PIN_MODEM_CTS != 0 )
		{
			if ( --CTS_TimeOut == 0 )
			{
				ModemStatus = MODEM_NOT_ANSWER;
				return;
			}
		}
#endif

		while (!(U2LSR & 0x20))
			continue;
		U2THR = ch; 
	}
	else
		if ( port == FOUT_DEV_U0 )
		{
			while (!(U0LSR & 0x20))
				continue;
			U0THR = ch;
		}
		else
			if ( port == FOUT_DEV_U3 )
			{
				while (!(U3LSR & 0x20))
					continue;
				U3THR = ch;
			}
}

void putsf( const char *s, int Port )
{
	while ( *s )	
		putch(*s++, Port);
}

void putstr( char *s, int Port )
{
	while ( *s )	
		putch(*s++, Port );
}

void putsn (unsigned char *s, unsigned char Port, unsigned int length )		// put a string with define string length
{
	while ( length-- )
	{
		putch( *s++, Port );
	}
}

#endif


/* --------------------------------------------------------------------------------------------------- */


/* void UART1_Init ( unsigned long br ) */
/* { */
/* /\* 	PINSEL0 |= 0x40000000; // Select UART1 TXD *\/ */
/* /\* 	PINSEL1 |= 0x00000001; // Select UART1 RXD *\/ */
/* /\* 	FIO2DIR &= ~(1UL<<1); *\/ */
/* /\* 	FIO2DIR &= ~(1UL<<0); *\/ */

/* 	PINMODE4 |= 0x0000000A; // no pull-up resistors */
/* 	PINSEL4 = 0; */
/* 	//PINSEL4 |= 0x0000000A; // Select UART1 TXD */
/* 	PINSEL4 |= 0x00000008; // Select UART1 RXD */
/* 	PINSEL4 |= 0x00000002; // Select UART1 TXD */

/* 	PINSEL4 |= 0x00000008; // Select UART1 RXD */
/* 	PINSEL4 |= 0x00000002; // Select UART1 TXD */

/* 	PINSEL4 |= 0x00000008; // Select UART1 RXD */
/* 	PINSEL4 |= 0x00000002; // Select UART1 TXD */
	
/* 	//	PINSEL10 = 0; */
	
	
/* 	U1IER = 0;		                       // disable all interrupts */
/* 	U1IIR;                                // clear interrupt ID */
/* 	U1RBR;                                // clear receive register */
/* 	U1LSR;                                // clear line status register */

/* 	U1FCR = 7; // Enable and clear FIFO's */
/* 	U1LCR = 0x83; // 8N1, enable Divisor latch bit */
/* 	/\* 	U1DLL = (unsigned char)(UART_BAUD(9600)); // baud rate fixed to 19200 @ PCLK = 12 Mhz *\/ */
/* /\* 	U1DLM = (unsigned char)((UART_BAUD(9600))>>8); // baud; *\/ */

/* 	U1DLL = (unsigned char)((PCLK/(br * 16))); // baud rate fixed to 19200 @ PCLK = 12 Mhz */
/* 	U1DLM = (unsigned char)(((PCLK/(br * 16)))>>8 ); // baud; */

/* 	U1LCR = 3; // Disable Divisor latch bit */


/*    U1MCR = 0; */
/* /\* 	FIO2DIR |= (1UL<<7); *\/ */
/* /\* 	FIO2PIN &= ~(1UL<<7); *\/ */

/* 	VICIntSelect    &= ~(1UL<<7); */
/* 	VICIntEnClr      = (1UL<<7); */
/* 	VICVectAddr7     = (unsigned int)GPS_Receiver; */
/* 	VICVectPriority7 = 15; */
/* 	VICIntEnable     = (1UL<<7); */
	
/* 	U1IER = UIER_RBR; */
/* } */

/* --------------------------------------------------------------------------------------------------- */

/* #define   TX_BUFSIZE		128 */
/* unsigned char TxBuf[TX_BUFSIZE]; */
/* void UART0_Tx_Int( void ) // Called from the main loop */
/* { */
/* 	int i; */

/* 	i = 16; */

/* 	if (U0LSR & 0x40) // transmit FIFO empty ? */
/* 	{ */
/* 		while(i && pData) */
/* 		{ */
/* 			U0THR = TxBuf[pTxBuf]; */
/* 			pData--; */
/* 			i--; */
/* 			pTxBuf++; */
/* 		} */
/* 	} */
/* } */

/* void SendString(const char *text) */
/* { */
/* 	if (pData == 0) // previous message send ? */
/* 	{ */
/* 		pTxBuf = 0; */
/* 		while(*text) */
/* 		{ */
/* 			TxBuf[pData++] = *text++; */
/* 			if(pData == TX_BUFSIZE) */
/* 				pData = 0; */
/* 		} */
/* 	} */
/* } */

/* static void Drive_UART0_TXD( void ) // Called from the main loop */
/* { */
/* 	unsigned char buf[16]; */
/* 	int i, bi; */
	
/* 	if ((U0LSR & 0x20)) // transmit FIFO empty ? */
/* 	{ */
/* 		i = Fifo_nRead(&Fifo_UART[SER_PORT_0], buf, 16); */
/* 		bi = 0; */
/* 		while( i ) */
/* 		{ */
/* 			U0THR = buf[bi]; */
/* 			bi++; */
/* 			i--; */
/* 		} */
/* 	} */
/* } */

/* static void Drive_UART1_TXD( void ) // Called from the main loop */
/* { */
/* 	unsigned char buf[16]; */
/* 	int i, bi; */
	
/* 	if (U1LSR & 0x20) // transmit FIFO empty ? */
/* 	{ */
/* 		i = Fifo_nRead(&Fifo_UART[SER_PORT_1], buf, 16); */
/* 		bi = 0; */
/* 		while( i ) */
/* 		{ */
/* 			U1THR = buf[bi]; */
/* 			bi++; */
/* 			i--; */
/* 		} */
/* 	} */
/* } */

/* static void Drive_UART2_TXD( void ) // Called from the main loop */
/* { */
/* 	unsigned char buf[16]; */
/* 	int i, bi; */

/* 	if (U2LSR & 0x20) // transmit FIFO empty ? */
/* 	{ */
/* 		i = Fifo_nRead(&Fifo_UART[SER_PORT_2], buf, 16); */
/* 		bi = 0; */
/* 		while( i ) */
/* 		{ */
/* 			U2THR = buf[bi]; */
/* 			bi++; */
/* 			i--; */
/* 		} */
/* 	} */
/* } */


/* void Drive_UARTs ( void ) */
/* { */
/* 	/\* Transmit *\/ */
/* 	Drive_UART0_TXD(); */
/* 	//Drive_UART1_TXD(); */
/* 	Drive_UART2_TXD(); */
/* } */

/* void UART1_Tx_Int(void) // Called from the main loop */
/* { */
/* 	char i = 16; */
/* 	if (U1LSR & 0x20) // transmit FIFO empty ? */
/* 	{ */
/* 		while (i && pData) */
/* 		{ */
/* 			U1THR = TxBuf[pTxBuf++]; */
/* 			pData--; */
/* 			i--; */
/* 		} */
/* 	} */
/* } */

/* int main (void) */
/* { */
/* 	UART1_Init(); */
/* 	while (1) */
/* 	{ */
/* 		SendString("Hello magnificent world of the LPC2000\r\n"); */
/* 		UART1_Tx_Int(); */
/* 	} */
/* }  */


// #define UART_BAUD(baud) (unsigned int)((PCLK / ((baud) * 16.0)) + 0.5)

// ----------------------------------------------------------------------------------------

/* int UART_putData ( char* Data, unsigned int ByteCount, unsigned int PortNumber ) */
/* { */
/* 	int Result; */

/* 	Result = Fifo_Write(&Fifo_UART[PortNumber], Data, ByteCount);  */
	
/* 	return Result; */
/* } */

/* int UART_puts ( void* ds, unsigned int PortNumber ) */
/* { */
/* 	int Result; */

/* 	char* s = ds; */

/* 	if ( s == NULL  ) */
/* 	{ */
/* 		return (-1); */
/* 	} */

/* 	Result = StrLen(s); */
/* 	if ( Result == 0 || Result == (-1) ) */
/* 	{ */
/* 		return (-1); */
/* 	} */
/* /\* 	Result = Fifo_Write( &Fifo_UART[PortNumber], s, (StrLen((char*)s)+1) );  *\/ */
/* /\* 	Fifo_UART[PortNumber].FifoBuffer[Fifo_UART[PortNumber].pWrite-1] = '\n'; /\\* ???? *\\/ *\/ */

/* 	Result = Fifo_Write( &Fifo_UART[PortNumber], s, Result );  */

/* 	if ( Result != -1 ) */
/* 	{ */
/* 		Result = 0; */
/* 	} */
	
/* 	return Result; */
/* } */
